package com.bjpowernode.money.web;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSONObject;
import com.bjpowernode.money.Constant;
import com.bjpowernode.money.HttpClientUtils;
import com.bjpowernode.money.Result;
import com.bjpowernode.money.model.FinanceAccount;
import com.bjpowernode.money.model.User;
import com.bjpowernode.money.service.FinanceAccoutService;
import com.bjpowernode.money.service.RedisService;
import com.bjpowernode.money.service.UserService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@Controller
public class UserController {

    @Reference(interfaceClass = UserService.class,version = "1.0.0",timeout = 20000,check = false)
    UserService userService;
    @Reference(interfaceClass = RedisService.class,version = "1.0.0",timeout = 20000,check = false)
    RedisService redisService;
    @Reference(interfaceClass = FinanceAccoutService.class,version = "1.0.0",timeout = 20000,check = false)
    FinanceAccoutService financeAccoutService;

    //注册页面的跳转
    @RequestMapping("/loan/page/register")
    public String register(){

        return "register";
    }

    //验证手机号是否已被注册
    @RequestMapping("/loan/page/checkPhone")
    @ResponseBody //要求必须传入一个手机号的参数
    public Object checkPhone(@RequestParam(name = "phone",required = true)String phone){
        System.out.println("-----checkPhone-----------");
        // User user= userService.queryUserByPhone(phone);  不能这样写，相当于拿到用户手机号就获得了用户其他的所以信息了
        int num = userService.queryUserCountByPhone(phone);
        if (num>=1){
           return Result.error("该手机号已被注册");
        }

        return Result.success();
    }

    @PostMapping("/loan/page/registerSubmit")
    @ResponseBody
    public Object registerSubmit(@RequestParam(name="phone",required = true)String phone,
                                 @RequestParam(name="loginPassword",required = true)String loginPassword,
                                 @RequestParam(name="messageCode",required = true)String messageCode,
                                 HttpServletRequest request){

        //验证输入的短信验证码是否正确，从Redis中取出
        String code = redisService.pop(phone);
        if(!StringUtils.equals(messageCode,code)){
            //如果短信验证码不正确的话
            return Result.error("验证码有误");
        }

        User user =userService.register(phone,loginPassword);
        if (!ObjectUtils.allNotNull(user)){
            //user是null 数目注册失败
            return Result.error("注册失败");
        }
        //注册成功 缓存在session中
        request.getSession().setAttribute(Constant.LOGIN_USER,user);

        return  Result.success();
    }

    @GetMapping("/loan/page/messageCode")
    @ResponseBody
    public Object messageCode(@RequestParam(name="phone",required = true)String phone){

        //httpClient:模拟客户端浏览器
        String code=Result.generateCode(6); //生成一个随机数6位
        Map<String,String> parasMap=new HashMap<String,String>();
        parasMap.put("appkey","672b58b4a5547dde2f72cdadc9f9800d");
        parasMap.put("mobile",phone);
        parasMap.put("content","【凯信通】您的验证码是："+code);
        //模拟报文
        String result="{\n" +
                "    \"code\": \"10000\",\n" +
                "    \"charge\": false,\n" +
                "    \"remain\": 0,\n" +
                "    \"msg\": \"查询成功\",\n" +
                "    \"result\": \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\" ?><returnsms>\\n <returnstatus>Success</returnstatus>\\n <message>ok</message>\\n <remainpoint>-7659165</remainpoint>\\n <taskID>194270051</taskID>\\n <successCounts>1</successCounts></returnsms>\",\n" +
                "    \"requestId\": \"8fb37df999e642209743603bda057a24\"\n" +
                "}";
        try {
            //模拟客户端浏览器在后台，来帮我们发送请求和获取响应的值
          // result = HttpClientUtils.doGet("https://way.jd.com/kaixintong/kaixintong",parasMap);
        } catch (Exception e) {
            e.printStackTrace();
            Result.error("短信发送失败,请再次发送");
        }

        //对上面模拟报文进行解析
        JSONObject jsonObject = JSONObject.parseObject(result);
        //获取解析后里面的code信息
        String code1 = jsonObject.getString("code");
        if(StringUtils.equals("1000",code1)){ //这个方法 不用考虑空指针的情况了
            Result.error("通信异常");
        }
        //当通信正常的话 要获取result中的值了
        String xml = jsonObject.getString("result");//返回的是一个xml格式的字符串
        //加入了解析xml文件的依赖，对它来解析，变成一个document文档
        Document document = null ;
        try {
            //异常里面代码不易写多 执行效率比较低
            document = DocumentHelper.parseText(xml);
        } catch (DocumentException e) {
            e.printStackTrace();
            Result.error("短信发送失败,请再次发送");
        }
        String text = document.selectSingleNode("//returnstatus").getText();
        if (!StringUtils.equals("Success",text)){
            Result.error("短信发送失败，请稍后再试");
        }
        /**
         * 将得到的短信验证码 存放在Redis中
         * redis中存的是Map数据类型，key和value，key的值保持唯一，可以用phone手机号去做key
         */

        redisService.push(phone,code);

        //返回了验证码 主要是想在前台可以看到
        //这个6位短信验证码是放在了success中的message中了，和success里面的code不一样，前段是判断success的code信息
        return Result.success(code);
    }

    //跳转到实名认证页面
    @GetMapping("/loan/page/realName")
    public String realName(){

        return "realName";
    }

    //实名认证的完成
    @RequestMapping("/loan/page/realNameSubmit")
    @ResponseBody
    public Object realNameSubmit(@RequestParam(name="phone",required = true)String phone,
                                 @RequestParam(name="realName",required = true)String realName,
                                 @RequestParam(name="idCard",required = true)String idCard,
                                 @RequestParam(name="messageCode",required = true)String messageCode,
                                 HttpServletRequest request){

        //验证输入的短信验证码是否正确，从Redis中取出
        String code = redisService.pop(phone);
        if(!StringUtils.equals(messageCode,code)){
            //如果短信验证码不正确的话
            return Result.error("验证码有误");
        }

        //是否登录，下面更新认证信息的时候 需要当前该用户的id信息 根据id更新
        //举例这种场景的发生：用户之前登录到认证页面，但是突然有事过了一会回来session失效 需要重新登录
        User user = (User) request.getSession().getAttribute(Constant.LOGIN_USER);
        if(user==null){
            return Result.error(-1,"请重新登录"); //在result中重写写了一个重载方法
        }

        //验证身份证信息是否正确
        Map<String,Object> parasMap=new HashMap<String,Object> ();
        parasMap.put("appkey","672b58b4a5547dde2f72cdadc9f9800d");
        parasMap.put("cardNo",idCard);
        parasMap.put("realName",realName);
        String result ="{\n" +
                "    \"code\": \"10000\",\n" +
                "    \"charge\": false,\n" +
                "    \"remain\": 1305,\n" +
                "    \"msg\": \"查询成功\",\n" +
                "    \"result\": {\n" +
                "        \"error_code\": 0,\n" +
                "        \"reason\": \"成功\",\n" +
                "        \"result\": {\n" +
                "            \"realname\": \"乐天磊\",\n" +
                "            \"idcard\": \"350721197702134399\",\n" +
                "            \"isok\": true\n" +
                "        }\n" +
                "    }\n" +
                "}";
        try {
            //result = HttpClientUtils.doPost("https://way.jd.com/youhuoBeijing/test", parasMap);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("实名认证失败");
        }
        JSONObject jsonObject = JSONObject.parseObject(result);
        String code1 = jsonObject.getString("code");
        if(!StringUtils.equals("10000",code1)){
            return  Result.error("通信异常");
        }
        Boolean isok = jsonObject.getJSONObject("result").getJSONObject("result").getBoolean("isok");
        if(!isok){
            return Result.error("身份证与姓名不匹配");
        }

        //更新用户信息
        User userReal = new User();
        userReal.setId(user.getId());
        userReal.setIdCard(idCard);
        userReal.setName(realName);
        int num = userService.userReal(userReal);
        if(num==0){
            return Result.error("用户认证失败");
        }
        return  Result.success();
    }

    //点击登录按钮，跳转到登录页面
    @RequestMapping("/loan/page/login")
    public String login(String ReturnUrl, Model model){
        model.addAttribute("ReturnUrl",ReturnUrl);
        return "login";
    }

    //点击登录按钮 对登录信息进行验证
    @RequestMapping("/loan/page/loginSubmit")
    @ResponseBody
    public Object loginSubmit(@RequestParam(name = "phone",required = true)String phone,
                              @RequestParam(name = "loginPassword",required = true)String loginPassword,
                              HttpServletRequest request){

        //1、根据账号和密码在数据库中进行匹配查询是否有对应的User对象，这种看不出来是账号还是密码错误
        //2、根据账号去查，得到密码后再进行匹配，可以知道是哪个错误
        User user = userService.login(phone,loginPassword);
        if(!ObjectUtils.allNotNull(user)){
            //说明账号或密码异常
            return Result.error("账号或密码不正确");
        }

        //登录成功后 将用户信息 缓存在session中
        request.getSession().setAttribute(Constant.LOGIN_USER,user);

        return Result.success();
    }

    //头部 退出功能的实现
    @RequestMapping("/loan/logout")
    public String logout(HttpServletRequest request){

        //退出之前需要将session中的对象清除
        request.getSession().invalidate();
        return "login";
    }

    //头部 进入我的小仓库
    @RequestMapping("/loan/page/myCenter")
    public String myCenter(HttpServletRequest request){

        //判断是否登录
        User user = (User) request.getSession().getAttribute(Constant.LOGIN_USER);
        if(!ObjectUtils.allNotNull(user)){
            //说明账号或密码异常
            return "login";
        }

        //根据uid查询所对应的账号余额信息
        FinanceAccount financeAccount = financeAccoutService.queryFinanceAccountByUserId(user.getId());
        Double availableMoney =  financeAccount.getAvailableMoney();
        request.getSession().setAttribute("availableMoney",String.valueOf(availableMoney));

        return "myCenter";
    }


}
